package com.tarena.lbs.content.service.impl;

import com.tarena.lbs.base.protocol.exception.BusinessException;
import com.tarena.lbs.common.enums.PassportResultEnum;
import com.tarena.lbs.common.principle.UserPrinciple;
import com.tarena.lbs.common.utils.AuthenticationContextUtils;
import com.tarena.lbs.content.dao.mapper.CategoryMapper;
import com.tarena.lbs.content.dao.repository.ActionESRepository;
import com.tarena.lbs.content.dao.repository.ArticleESRepository;
import com.tarena.lbs.content.pojo.param.ArticleActionParam;
import com.tarena.lbs.content.pojo.param.ArticleContentParam;
import com.tarena.lbs.content.pojo.po.ActionSearchPO;
import com.tarena.lbs.content.pojo.po.ArticleSearchPO;
import com.tarena.lbs.content.pojo.vo.ArticleVO;
import com.tarena.lbs.content.service.ArticleService;
import com.tarena.lbs.content.utils.SequenceGenerator;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.Optional;

/**
 * 文章业务模块实现类
 */
@Slf4j
@Service
public class ArticleServiceImpl implements ArticleService {
	
	@Autowired
	private CategoryMapper categoryMapper; // 文章分类MySQL
	@Autowired
	private ActionESRepository actionESRepository; // 行为记录ES仓库
	@Autowired
	private ArticleESRepository articleESRepository; // 文章ES仓库
	
	/**
	 * 记录用户行为
	 *
	 * @param param 文章行为参数
	 * @throws BusinessException 业务异常
	 */
	@Override
	public void articleAction(ArticleActionParam param) throws BusinessException {
		log.debug(">>>开始记录用户行为：{}", param);
		
		// 校验参数，文章ID不能为空
		if (param.getId() == null) {
			throw new BusinessException(PassportResultEnum.ARTICLE_NOT_EXIST);
		}
		
		// 根据文章ID查询文章，并校验是否存在
		Optional<ArticleSearchPO> articlePOOptional = articleESRepository.findById(param.getId());
		if (articlePOOptional.isEmpty()) {
			throw new BusinessException(PassportResultEnum.ARTICLE_NOT_EXIST);
		}
		ArticleSearchPO articlePO = articlePOOptional.get();
		
		// 获取当前登录用户，并校验登录状态
		UserPrinciple userPrinciple = AuthenticationContextUtils.get();
		if (userPrinciple == null) {
			throw new BusinessException(PassportResultEnum.NOT_LOGIN);
		}
		
		// 收集待处理的行为类型
		List<Integer> behaviorTypes = new ArrayList<>();
		if (param.getAction() != null) behaviorTypes.add(param.getAction());
		if (param.getBehavior() != null) behaviorTypes.add(param.getBehavior());
		
		// 循环处理每个行为类型
		for (Integer behaviorType : behaviorTypes) {
			// 创建独立的行为记录对象
			ActionSearchPO actionPO = buildActionPO(articlePO, userPrinciple);
			// 处理单个行为
			processSingleBehavior(behaviorType, articlePO, actionPO, param);
		}
	}
	
	
	/**
	 * 保存文章至ES
	 *
	 * @param param 文章内容参数
	 * @throws BusinessException 业务异常
	 */
	@Override
	public void saveArticleToEs(ArticleContentParam param) throws BusinessException {
		log.debug(">>>开始保存文章到ES业务，{}", param);
		
		// 获取当前登录用户ID
		UserPrinciple userPrinciple = AuthenticationContextUtils.get();
		// 校验登录状态
		if (userPrinciple == null) {
			throw new BusinessException(PassportResultEnum.NOT_LOGIN);
		}
		
		// 创建ES实体对象
		ArticleSearchPO articleSearchPO = new ArticleSearchPO();
		// 复制属性
		BeanUtils.copyProperties(param, articleSearchPO);
		// 设置创建时间
		articleSearchPO.setCreateTime(new Date());
		// 拼接位置信息
		if (param.getLatitude() != null && param.getLongitude() != null) {
			articleSearchPO.setLocation(param.getLatitude() + "," + param.getLongitude());
		}
		// 设置默认值
		articleSearchPO.setAccessCount(param.getAccessCount() != null ? param.getAccessCount() : 0);
		articleSearchPO.setLikeCount(param.getLikeCount() != null ? param.getLikeCount() : 0);
		articleSearchPO.setFavoriteCount(param.getFavoriteCount() != null ? param.getFavoriteCount() : 0);
		// 设置用户ID
		Integer userId = userPrinciple.getId();
		articleSearchPO.setUserId(userId);
		// 设置文章ID
		Integer sequenceId = SequenceGenerator.sequence();
		articleSearchPO.setId(sequenceId);
		
		// 保存并回填ID
		ArticleSearchPO savedArticle = articleESRepository.save(articleSearchPO);
		
		log.debug(">>>文章保存到ES业务成功");
		// TODO 调用附件服务绑定图片
	}
	
	/**
	 * 根据ID查询文章详情
	 *
	 * @param id 文章ID
	 * @return 文章详情VO对象
	 * @throws BusinessException 业务异常
	 */
	@Override
	public ArticleVO getArticleDetailById(String id) throws BusinessException {
		log.debug(">>>开始根据ID查询文章详情业务，{}", id);
		
		// 将文章ID转换为整数，并校验格式
		Integer articleId;
		try {
			articleId = Integer.parseInt(id);
		} catch (NumberFormatException e) {
			throw new BusinessException(PassportResultEnum.ARTICLE_NOT_EXIST);
		}
		
		// 查询文章详情，并校验
		Optional<ArticleSearchPO> articleSearchPO = articleESRepository.findById(articleId);
		if (articleSearchPO.isEmpty()) {
			throw new BusinessException(PassportResultEnum.ARTICLE_NOT_EXIST);
		}
		
		ArticleSearchPO articlePO = articleSearchPO.get();
		
		// TODO 记录用户行为
		// TODO 检查活动信息
		
		// 增加访问量
		articlePO.setAccessCount(articlePO.getAccessCount() + 1);
		// 保存至ES
		articleESRepository.save(articlePO);
		
		// 转换为VO对象
		ArticleVO articleVO = new ArticleVO();
		BeanUtils.copyProperties(articlePO, articleVO);
		
		log.debug(">>>根据ID查询文章详情业务成功，{}", articleVO);
		return articleVO;
	}
	
	// 构建行为记录基础对象
	private ActionSearchPO buildActionPO(ArticleSearchPO articlePO, UserPrinciple userPrinciple) {
		ActionSearchPO actionPO = new ActionSearchPO();
		actionPO.setArticleUserId(articlePO.getUserId());
		actionPO.setArticleTitle(articlePO.getArticleTitle());
		actionPO.setArticleId(articlePO.getId());
		actionPO.setArticleLabel(articlePO.getArticleLabel());
		actionPO.setArticleType(categoryMapper.selectById(articlePO.getArticleCategoryId()).getCategoryName());
		actionPO.setBehaviorUserId(userPrinciple.getId());
		actionPO.setCreateTime(new Date());
		return actionPO;
	}
	
	// 处理单个行为类型
	private void processSingleBehavior(Integer behaviorType, ArticleSearchPO articlePO,
	                                   ActionSearchPO actionPO, ArticleActionParam param) throws BusinessException {
		// 跳过无效行为类型
		if (behaviorType == null || behaviorType < 1 || behaviorType > 3) {
			log.warn("无效行为类型：{}，跳过处理", behaviorType);
			return;
		}
		
		// 行为类型差异化处理
		switch (behaviorType) {
			case 1: // 点赞
				articlePO.setLikeCount(articlePO.getLikeCount() + 1);
				actionPO.setBehavior(1);
				break;
			case 2: // 收藏
				articlePO.setFavoriteCount(articlePO.getFavoriteCount() + 1);
				actionPO.setBehavior(2);
				break;
			case 3: // 评论
				String comment = param.getComment();
				if (StringUtils.isBlank(comment)) {
					throw new BusinessException(PassportResultEnum.COMMENT_CONTENT_EMPTY);
				}
				actionPO.setComment(comment);
				actionPO.setBehavior(3);
				break;
		}
		
		// 统一保存行为记录和文章状态
		actionESRepository.save(actionPO);
		articleESRepository.save(articlePO);
		log.debug(">>>用户行为记录完成，记录ID：{}", actionPO.getId());
	}
	
}
